<!--
 * @Author: Damon Liu
 * @Date: 2025-04-03 10:26:51
 * @LastEditors: Damon Liu
 * @LastEditTime: 2025-04-09 11:51:39
 * @Description: 
-->
<template>
    <div class="tomato-ctn"
        :style="{ left: `${props.position.pageX}px`, top: `${props.position.pageY}px`, transform: transformText }">
        <GoodTomato v-if="!isBroken" class="good-tomato">
        </GoodTomato>
        <BadTomato class="bad-tomato" v-else :style="{ transform: `scale(${scale * 3})` }"></BadTomato>
        <div v-if="isMiss" class="unhit-tips" :style="{ transform: `scale(${1 / scale})` }">
            未命中！！
        </div>
    </div>
</template>

<script setup>
import { computed, onMounted, ref, toRaw } from 'vue';
import GoodTomato from '../assets/tomato_good.svg';     // 完好的番茄
import BadTomato from '../assets/tomato.svg';           // 坏掉的番茄
const props = defineProps({
    position: {
        default: () => {
            return {
                clientX: -100,
                clientY: -100,
                pageX: -100,
                pageY: -100
            }
        }
    }
})

const x = ref(props.position.pageX);    // 元素当前的pageX

const y = ref(props.position.pageY);    // 元素当前的pageY

const eX = ref(0);             // 元素最终的位置pageX

const eY = ref(0);              // 元素最终的位置pageY

const pageX = ref(0);   // 点击时候的pageX

const pageY = ref(0);   // 点击时候的pageY

const scale = ref(1);               // 缩放倍率

const isBroken = ref(false);        // 控制番茄样式
/**
 * 模拟从点击点到目标点的抛物线轨迹（可调节弯度）
 * @param {number} y1 - 当前纵向坐标
 * @param {number} startY - 起始点的纵坐标 (y)
 * @param {number} targetX - 目标点的横坐标 (x ± 20)
 * @param {number} startX - 起始点的横坐标 (x)
 * @param {number} [curvature=4] - 控制抛物线弯度的参数（值越大，弯度越明显）
 * @returns {number} x1 - 对应纵坐标 y1 的横坐标
 */
function parabolicTrajectory(y1, startY, targetX, startX, curvature = 4) {
    // 计算纵向总距离
    const totalYDistance = 100; // y + 200 - y = 200
    // 计算当前纵向位置占总距离的比例 (0 到 1)
    const t = (y1 - startY) / totalYDistance;

    // 如果 y1 不在起始点和目标点之间，返回边界值
    if (t <= 0) return startX;
    if (t >= 1) return targetX;

    // 计算横向总距离（可能是正或负，取决于目标点在左还是右）
    const totalXDistance = targetX - startX;

    // 使用抛物线方程 x = startX + totalXDistance * t + (调整弯度的二次项)
    // 二次项系数 curvature 控制弯度（默认 4，值越大弯度越明显）
    const x1 = startX + totalXDistance * t + (-curvature * totalXDistance * t * (1 - t));

    return x1;
}

// 位置偏移量
const transformText = computed(() => {
    // 偏移量为： 当前坐标 - 起始坐标 - 32（元素的长宽为64，以中心为基点，所以减去32）
    return `translate(${pageX.value -props.position.pageX - 32}px, ${pageY.value -props.position.pageY - 32}px) scale(${scale.value})`;
})

const timer = ref();    // 动画的timer

const targetEl = ref();     // 最终集中的目标元素

const isMiss = ref(false);      // 是否命中

// 命中
const attack = () => {
    // 当元素存在的时候
    if (targetEl.value) {
        // 创建一个原生的鼠标点击事件
        const clickEvent = new MouseEvent('click', {
            bubbles: true,       // 事件是否冒泡
            cancelable: true,    // 事件是否可以取消
            view: window,        // 关联的窗口对象
            clientX: x.value,          // 指定的 X 坐标（相对于视口）
            clientY: y.value,           // 指定的 Y 坐标（相对于视口）
            detail: 1002        // 用于区分时间是 代码触发  还是  人为触发
        });

        // 触发原生点击事件
        targetEl.value.dispatchEvent(clickEvent);
    } else {
        console.log('没有找到对应坐标的元素');
        isMiss.value = true;        // 没有命中
    }
}

// 开始动画
const startAnimate = () => {
    const oneStep = (eY.value - y.value) / 200; // 分 200步 执行
    const oneScaleStep = (0.6) / 200;   // 分 200步 执行
    timer.value = setInterval(() => {
        // 当没有到达终点位置的时候持续更新
        if (pageY.value + oneStep < eY.value) {
            pageY.value = pageY.value + oneStep;
            scale.value = scale.value - oneScaleStep;
            pageX.value = parabolicTrajectory(pageY.value, props.position.pageY, eX.value, props.position.pageX, 15);
        }
        else {
            timer.value && clearInterval(timer.value);
            timer.value = null;
            isBroken.value = true;  // 更新为烂番茄
            attack();   // 触发命中事件
        }
    }, 10);
}

onMounted(() => {
    // 初始化pageX和pageY
    pageX.value = props.position.pageX;   
    pageY.value = props.position.pageY;
    //let randomX = parseInt(Math.random() * 200 - 100);
    // x的随机偏移量， ±30 偏移一下
    let randomXMius = parseInt(Math.random() * 60 - 30);
    // 终止位置的pageX和pageY的值
    eX.value = pageX.value + randomXMius;
    eY.value = pageY.value + 100;
    // 计算当前终止的clientX和ClientY, 用于获取点击时最终击中的目标元素
    const currentEndClientX = props.position.clientX + randomXMius;
    const currentEndClientY = props.position.clientY + 100;
    targetEl.value = document.elementFromPoint(currentEndClientX, currentEndClientY);
    // 开始动画
    startAnimate();
})

</script>

<style lang="less" scoped>
.good-tomato {
    width: 64px;
    height: 64px;
    animation: rotateScale .3s infinite ease;
}

.bad-tomato {
    width: 64px;
    height: 64px;
}

.tomato-ctn {
    width: 64px;
    height: 64px;

    /* 应用动画 */
    position: absolute;
}

.unhit-tips {
    color: red;
    position: absolute;
    top: -24px;
    text-align: center;
    width: 100px;
    user-select: none;
    animation: tipAnimation .8s ease-in-out forwards;
}

@keyframes tipAnimation {
    0% {
        top: -24px;
        opacity: 1;
    }
    40% {
        top: -38px;
        opacity: 0.5;
    }
    80% {
        top: -50px;
        opacity: 0.1;
    }
    100% {
        display: none;
    }
}

/* 定义动画 */
@keyframes rotateScale {
    0% {
        transform: rotate(0deg);
        /* 初始状态：无旋转，正常大小 */
    }

    50% {
        transform: rotate(180deg);
        /* 中间状态：旋转180度，放大1.5倍 */
    }

    100% {
        transform: rotate(360deg);
        /* 结束状态：旋转360度，恢复原大小 */
    }
}
</style>
